#pragma once
#include <condition_variable>
#include <regex>
#include <mutex>
#include <queue>
#include <functional>
#include "../message/interface/MessageInterface.hpp"

namespace MessageSynthesisTool {

    /**
     * 消息池
     * @tparam MESSAGE_TYPE
     */
    template<typename MESSAGE_TYPE>
    class MessagePools {
    private:

        class MessageObjectPool {
        private:
            TYPE m_messageTYpe;

            std::queue<MessageInterface<TYPE>*> m_unusedPool;
            std::unordered_set<MessageInterface<TYPE>*> m_usedPool;
            std::mutex m_mutex;


            // 使用函数工厂来创建消息对象
            std::function<MessageInterface<TYPE>*()> m_creaObjectFun;

            int m_poolSize;

        private:
            /**
             *
             * @param quantity
             */
            void addMessageToPool(int quantity) {
                for (int i = 0; i < quantity; i++)
                    this->m_unusedPool.emplace(this->m_creaObjectFun());
            }

        public:

            /**
             *
             * @param creaObjectFun
             * @param poolSize
             */
            MessageObjectPool(const std::function<MessageInterface<TYPE>*()>& creaObjectFun ,int poolSize = 20) {
                this->m_creaObjectFun = creaObjectFun;

                //先创建一个实例获取格式
                MessageInterface<TYPE>* message = this->m_creaObjectFun();
                this->m_messageTYpe = message->getType();
                //将创建的实例加入池中
                this->m_unusedPool.push(message);

                this->m_poolSize = poolSize;


                //初始化池由于已经将一个实例加入池中所以数量-1
                this->addMessageToPool(poolSize-1);
            }

            ~MessageObjectPool() {
                while (!this->m_unusedPool.empty()) {
                    MessageInterface<TYPE>* messageObject = this->m_unusedPool.front();
                    this->m_unusedPool.pop();
                    delete messageObject;
                }

                for (auto& message : this->m_usedPool) {
                    MessageInterface<TYPE>* messageObject = message;
                    this->m_usedPool.erase(message);
                    delete messageObject;
                }
            }

            /**
             *
             * @return
             */
            MessageInterface<TYPE>* acquireMessgeObject() {
                std::unique_lock<std::mutex> lock(this->m_mutex);

                //消息池已分配完，扩容消息池
                if (this->m_unusedPool.empty()) {
                    int quantity = this->m_poolSize*0.5;
                    this->addMessageToPool(quantity);
                    this->m_poolSize+=quantity;
                }

                MessageInterface<TYPE>* message = this->m_unusedPool.front();
                this->m_unusedPool.pop();
                this->m_usedPool.insert(message);

                return message;
            }

            /**
             *
             * @param messageObject
             */
            void releaseMessageObeject(MessageInterface<TYPE>* messageObject) {
                std::unique_lock<std::mutex> lock(this->m_mutex);
                this->m_usedPool.erase(messageObject);
                this->m_unusedPool.push(messageObject);
            }
        };

    private:

        //检测消息格式的正则表达式
        static const std::regex checkMessagePattern;
        //提取键值对的表达式
        static const std::regex KVPattern;
        std::unordered_map<TYPE,std::shared_ptr<MessageObjectPool>> m_messagesObjectsPools;

        int m_defaultPoolSize;

    public:

        //检测消息格式的正则表达式
        static const std::regex checkMessagePattern;
        //提取键值对的表达式
        static const std::regex KVPattern;
        std::unordered_map<MESSAGE_TYPE,std::shared_ptr<MessageObjectPool>> m_messagesObjectsPools;

        int m_defaultPoolSize;

    public:

        MessagePools(int defaultPoolSize = 20) {
            this->m_defaultPoolSize = defaultPoolSize;
        }

        ~MessagePools() {}


        /**
         *
         * @tparam MESSAGE
         * @param messageStr
         * @param messagePointer
         * @return
         */
        template<typename MESSAGE>
        bool acquireMessge(std::string& messageStr, MESSAGE*& messagePointer) {
            if (!std::regex_search(messageStr,MessagePoolsTool<TYPE>::checkMessagePattern))
                return false;

            //提取键值对
            auto wordsBegin = std::sregex_iterator(messageStr.begin(),messageStr.end(),MessagePoolsTool<TYPE>::KVPattern);
            auto wordsEnd = std::sregex_iterator();
            std::unordered_map<std::string, std::string> keyValuePairs;
            for (std::sregex_iterator it = wordsBegin; it!=wordsEnd; ++it) {
                std::smatch match = *it;
                keyValuePairs[match[1]] = match[2];
            }

            //没有type键值对
            auto keyValuePairsIt = keyValuePairs.find("type");
            if (keyValuePairsIt == keyValuePairs.end()) return false;

            try {
                TYPE messageType = static_cast<TYPE>(std::stoi(keyValuePairsIt->second)); //调用该函数有异常可能

                //超出消息样式范围
                if (messageType >= TYPE::END || messageType <= TYPE::BEGIN)
                    return false;

                //寻找该类型的消息数组
                auto messagesObjectsPoolsIt = this->m_messagesObjectsPools.find(messageType);

                //不存在该类型消息池，则创建该类型消息池
                if (messagesObjectsPoolsIt == this->m_messagesObjectsPools.end()) {
                    // 使用正确的模板参数创建MessageObjectPool
                    auto createMessageObjectFun = []() {
                        return new MESSAGE();
                    };
                    auto pool = std::make_shared<MessageObjectPool>(createMessageObjectFun,this->m_defaultPoolSize);
                    messagesObjectsPoolsIt = this->m_messagesObjectsPools.emplace(messageType, pool).first;
                }

                //从池中获取Message
                MessageInterface<TYPE>* messageObject = messagesObjectsPoolsIt->second-> acquireMessgeObject();

                //将MessageObject类型转化成指定的消息类型
                messagePointer = static_cast<MESSAGE*>(messageObject);

                //通过键值对初始化消息
                messagePointer->initializetionByKeyValuePairs(keyValuePairs);

                std::cout << messagePointer << std::endl;

                return true;

            }
            catch (...) {return false;}
        }


        /**
         *
         * @tparam MESSAGE
         * @param messagePointer
         */
        template<typename MESSAGE>
        void releaseMessage(MESSAGE* messagePointer) {
            auto messagesObjectsPoolsIt = this->m_messagesObjectsPools.find(messagePointer->getType());

            if (messagesObjectsPoolsIt == this->m_messagesObjectsPools.end()) return;

            //清除数据
            messagePointer->clear();

            messagesObjectsPoolsIt->second.get()->releaseMessageObeject(messagePointer);
        }
    };

    /**
     * 消息处理器
     * @tparam MESSAGE_TYPE
     */
    template<typename MESSAGE_TYPE>
    class MessageProcessor {
    private:
        class MessageQueue {
        private:
            std::mutex m_mutex;
            std::queue<MessageInterface<MESSAGE_TYPE>*> m_messageQueue;
            std::condition_variable m_conditionVariable;
            std::function<bool()> m_handleFun;
            bool m_handled;

        public:
            /**
             *
             * @param handleFun
             */
            MessageQueue(std::function<bool()> handleFun) {
                this->m_handleFun = handleFun;
                this->m_handled = false;
            }

            ~MessageQueue() {}

            void handle(){}
        };


    public:



    };
};

template<typename MESSAGE_TYPE>
const std::regex MessageSynthesisTool::MessagePools<MESSAGE_TYPE>::checkMessagePattern = std::regex(R"(^\s*\{\s*[^\s;:]+\s*:\s*[^;:]+(?:\s*;\s*[^\s;:]+\s*:\s*[^;:]+)*\s*\}\s*$)");

template<typename MESSAGE_TYPE>
const std::regex MessageSynthesisTool::MessagePools<MESSAGE_TYPE>::KVPattern = std::regex(R"(([^\s;:{]+)\s*:\s*([^;}]+)\s*)");